from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich.table import Table
from rich.prompt import Prompt, Confirm
from rich import box
from rich.align import Align
from typing import List, Dict, Any, Optional

class DetectiveUI:
    """侦探游戏用户界面"""
    
    def __init__(self):
        self.console = Console()
    
    def show_welcome(self):
        """显示欢迎界面"""
        title = Text()
        title.append("🕵️ ", style="bold blue")
        title.append("侦探推理游戏", style="bold cyan")
        title.append(" 🔍", style="bold yellow")
        
        welcome_panel = Panel(
            Align.center(title),
            title="欢迎来到推理世界",
            border_style="cyan",
            padding=(1, 2)
        )
        
        self.console.print(welcome_panel)
        self.console.print()
    
    def show_main_menu(self) -> str:
        """显示主菜单"""
        menu_text = """
1. 🔍 开始调查案件
2. 📖 查看游戏规则
3. 🚪 退出游戏
        """
        
        self.console.print(Panel(menu_text, title="主菜单", border_style="blue"))
        
        return Prompt.ask(
            "[bold blue]请选择[/bold blue]",
            choices=["1", "2", "3"],
            default="1"
        )
    
    def show_rules(self):
        """显示游戏规则"""
        rules_text = """
🕵️ 侦探推理游戏规则：

1. 🎯 游戏目标
   • 你是一名侦探，需要调查谋杀案
   • 在有限的轮次内找出真正的凶手
   • 通过对话收集信息，推理出真相

2. 💬 对话系统
   • 总共有15轮调查机会
   • 每次与角色对话消耗1轮
   • 每个角色都有自己的秘密和动机
   • 真凶会巧妙隐瞒，但不会完全撒谎

3. 💡 提示系统
   • 最多可以获取3次提示
   • 提示不消耗对话轮次
   • 合理利用提示可以帮助推理

4. ⚖️ 指认凶手
   • 轮次用完后必须做出最终指控
   • 也可以随时主动指认凶手
   • 只有一次指认机会，请谨慎选择

5. 🔍 调查技巧
   • 注意每个人的动机和不在场证明
   • 寻找时间线上的矛盾
   • 观察谁最有机会和动机

开始你的侦探之旅吧！
        """
        
        rules_panel = Panel(
            rules_text,
            title="📚 游戏规则",
            border_style="green"
        )
        
        self.console.print(rules_panel)
        input("\n按回车键返回主菜单...")
    
    def show_case_intro(self, case):
        """显示案件介绍"""
        self.console.print()
        
        # 案件标题
        title_text = Text()
        title_text.append("🔍 ", style="bold red")
        title_text.append(case.title, style="bold white")
        
        title_panel = Panel(
            Align.center(title_text),
            border_style="red",
            padding=(0, 2)
        )
        self.console.print(title_panel)
        
        # 案件详情
        case_info = f"""
📋 案件描述：{case.description}

💀 受害者：{case.victim_name}
📍 案发地点：{case.crime_scene}
⏰ 案发时间：{case.time_of_crime}

🎯 你的任务：找出真凶，还原真相！
        """
        
        info_panel = Panel(
            case_info,
            title="案件信息",
            border_style="yellow"
        )
        self.console.print(info_panel)
    
    def show_investigation_menu(self, current_round: int, max_rounds: int, hints_used: int, max_hints: int) -> str:
        """显示调查菜单"""
        hints_status = f"{max_hints - hints_used}/{max_hints}" if hints_used < max_hints else "已用完"
        hint_option = "2. 💡 获取提示" if hints_used < max_hints else "2. 💡 获取提示 (已用完)"
        
        menu_text = f"""
剩余轮次：{max_rounds - current_round}/{max_rounds}
剩余提示：{hints_status}

1. 💬 与角色对话
{hint_option}
3. ⚖️ 指认凶手
4. 🚪 结束调查
        """
        
        self.console.print(Panel(menu_text, title="调查选项", border_style="green"))
        
        return Prompt.ask(
            "[bold green]请选择调查行动[/bold green]",
            choices=["1", "2", "3", "4"],
            default="1"
        )
    
    def select_character(self, characters):
        """选择要对话的角色"""
        self.console.print(Panel("选择要对话的角色", title="角色列表", border_style="blue"))
        
        table = Table(box=box.ROUNDED)
        table.add_column("编号", style="cyan", no_wrap=True)
        table.add_column("姓名", style="bold white")
        table.add_column("年龄", style="yellow")
        table.add_column("身份", style="green")
        
        for i, char in enumerate(characters, 1):
            table.add_row(
                str(i),
                char.name,
                str(char.age),
                char.occupation
            )
        
        self.console.print(table)
        
        try:
            choice = int(Prompt.ask("请选择角色编号 (0=返回)")) - 1
            if 0 <= choice < len(characters):
                return characters[choice]
            elif choice == -1:
                return None
            else:
                self.show_error("无效的角色编号")
                return None
        except ValueError:
            self.show_error("请输入有效的数字")
            return None
    
    def show_character_info(self, character):
        """显示角色信息"""
        char_info = f"""
👤 {character.name} ({character.age}岁)
💼 {character.occupation}

💬 开始对话吧！
🚪 退出对话：选择QQ或直接按回车
        """
        
        char_panel = Panel(
            char_info,
            title=f"正在与 {character.name} 对话",
            border_style="blue"
        )
        self.console.print(char_panel)
    
    def get_question(self, suggested_questions: List[str] = None) -> str:
        """获取用户问题"""
        if suggested_questions:
            self.console.print(Panel("💡 推荐问题 (或输入自定义问题)", title="问题选择", border_style="yellow"))
            
            table = Table(box=box.ROUNDED)
            table.add_column("选项", style="cyan", no_wrap=True)
            table.add_column("问题", style="white")
            
            for i, question in enumerate(suggested_questions, 1):
                table.add_row(f"Q{i}", question)
            table.add_row("Q0", "自定义问题")
            table.add_row("QQ", "🚪 退出对话")
            
            self.console.print(table)
            
            choice = Prompt.ask("[bold blue]选择问题[/bold blue] (Q1/Q2/Q3/Q0/QQ)", default="Q1")
            
            if choice.upper() == "Q1" and len(suggested_questions) >= 1:
                return suggested_questions[0]
            elif choice.upper() == "Q2" and len(suggested_questions) >= 2:
                return suggested_questions[1]
            elif choice.upper() == "Q3" and len(suggested_questions) >= 3:
                return suggested_questions[2]
            elif choice.upper() == "QQ":
                return ""  # 空字符串表示退出
            elif choice.upper() == "Q0":
                custom_question = Prompt.ask("[bold blue]请输入你的问题[/bold blue] (直接回车退出对话)")
                return custom_question
            else:
                return Prompt.ask("[bold blue]请输入你的问题[/bold blue] (直接回车退出对话)")
        else:
            return Prompt.ask("[bold blue]你的问题[/bold blue] (直接回车退出对话)")
    
    def show_conversation(self, character, question: str, response: str):
        """显示对话内容"""
        # 显示问题
        q_text = Text()
        q_text.append("🕵️ 侦探：", style="bold blue")
        q_text.append(question, style="white")
        self.console.print(q_text)
        
        # 显示回答
        a_text = Text()
        a_text.append(f"👤 {character.name}：", style="bold green")
        a_text.append(response, style="italic green")
        self.console.print(a_text)
        
        self.console.print()
    
    async def show_streaming_conversation(self, character, question: str, response_stream):
        """显示流式对话内容"""
        import asyncio
        
        # 显示问题
        q_text = Text()
        q_text.append("🕵️ 侦探：", style="bold blue")
        q_text.append(question, style="white")
        self.console.print(q_text)
        
        # 显示角色名称
        a_prefix = Text()
        a_prefix.append(f"👤 {character.name}：", style="bold green")
        self.console.print(a_prefix, end="")
        
        # 流式显示回答
        full_response = ""
        async for chunk in response_stream:
            if chunk:
                # 使用绿色斜体显示回答内容
                chunk_text = Text(chunk, style="italic green")
                self.console.print(chunk_text, end="")
                full_response += chunk
                # 添加小延迟让流式效果更明显
                await asyncio.sleep(0.02)
        
        self.console.print()  # 换行
        self.console.print()
        
        return full_response
    
    def select_suspect(self, characters):
        """选择嫌疑人进行指控"""
        suspects = [char for char in characters if char.character_type.value == "suspect"]
        
        self.console.print(Panel("选择你要指控的嫌疑人", title="做出指控", border_style="red"))
        
        table = Table(box=box.ROUNDED)
        table.add_column("编号", style="cyan", no_wrap=True)
        table.add_column("姓名", style="bold white")
        table.add_column("身份", style="green")
        
        for i, suspect in enumerate(suspects, 1):
            table.add_row(str(i), suspect.name, suspect.occupation)
        
        self.console.print(table)
        
        try:
            choice = int(Prompt.ask("请选择嫌疑人编号 (0=返回)")) - 1
            if 0 <= choice < len(suspects):
                return suspects[choice]
            elif choice == -1:
                return None
            else:
                self.show_error("无效的嫌疑人编号")
                return None
        except ValueError:
            self.show_error("请输入有效的数字")
            return None
    
    def get_accusation_reasoning(self) -> str:
        """获取指控理由"""
        return Prompt.ask("[bold red]请说明你的指控理由[/bold red]")
    
    def show_success(self, suspect, solution: str, vote_info: str = None):
        """显示成功指控"""
        success_text = Text()
        success_text.append("🎉 恭喜！", style="bold green")
        success_text.append(f"指控成功！{suspect.name}被认定为凶手！", style="green")
        
        if vote_info:
            success_text.append(f"\n{vote_info}", style="italic green")
        
        success_panel = Panel(
            Align.center(success_text),
            title="指控成功",
            border_style="green",
            padding=(1, 2)
        )
        
        self.console.print(success_panel)
    
    def show_failure(self, suspect, solution: str, vote_info: str = None):
        """显示失败指控"""
        failure_text = Text()
        failure_text.append("😔 很遗憾！", style="bold red")
        failure_text.append(f"指控失败！{suspect.name}未被认定为凶手。", style="red")
        
        if vote_info:
            failure_text.append(f"\n{vote_info}", style="italic red")
        
        failure_panel = Panel(
            Align.center(failure_text),
            title="指控失败",
            border_style="red",
            padding=(1, 2)
        )
        
        self.console.print(failure_panel)
    
    def show_case_solution(self, case):
        """显示案件真相"""
        solution_text = Text(case.solution, style="italic white")
        solution_panel = Panel(
            solution_text,
            title="🔍 案件真相",
            border_style="cyan",
            box=box.DOUBLE
        )
        
        self.console.print(solution_panel)
        self.console.print()
    
    def show_error(self, message: str):
        """显示错误信息"""
        error_text = Text()
        error_text.append("❌ ", style="bold red")
        error_text.append(message, style="red")
        
        self.console.print(error_text)
        self.console.print()
    
    def show_goodbye(self):
        """显示告别信息"""
        goodbye_text = Text()
        goodbye_text.append("👋 ", style="bold blue")
        goodbye_text.append("感谢游玩侦探推理游戏！", style="blue")
        goodbye_text.append(" 🕵️", style="bold green")
        
        goodbye_panel = Panel(
            Align.center(goodbye_text),
            title="再见",
            border_style="blue",
            padding=(1, 2)
        )
        
        self.console.print(goodbye_panel)
    
    def show_hint(self, hint: str, used: int, max_hints: int, investigation_summary: str = None):
        """显示智能提示"""
        hint_text = f"""
💡 智能提示 ({used}/{max_hints})：

🔍 {hint}
        """
        
        # 如果有调查摘要，也显示出来
        if investigation_summary:
            hint_text += f"""
📊 当前调查状态：
{investigation_summary}
            """
        
        hint_panel = Panel(
            hint_text,
            title="💡 调查提示",
            border_style="yellow"
        )
        
        self.console.print(hint_panel)
        input("\n按回车键继续...")
    
    def show_rounds_exhausted(self):
        """显示轮次用完"""
        exhausted_text = Text()
        exhausted_text.append("⏰ 调查时间结束！", style="bold red")
        exhausted_text.append("你必须做出最终指控。", style="red")
        
        exhausted_panel = Panel(
            Align.center(exhausted_text),
            title="时间到",
            border_style="red",
            padding=(1, 2)
        )
        
        self.console.print(exhausted_panel)
    
    def show_remaining_rounds(self, current_round: int, max_rounds: int):
        """显示剩余轮次"""
        remaining = max_rounds - current_round
        if remaining <= 3:
            style = "bold red"
            warning = " ⚠️"
        elif remaining <= 5:
            style = "bold yellow"
            warning = " ⚡"
        else:
            style = "bold green"
            warning = ""
        
        rounds_text = Text()
        rounds_text.append(f"剩余轮次：{remaining}/{max_rounds}", style=style)
        rounds_text.append(warning, style=style)
        
        self.console.print(rounds_text)
        self.console.print()
    
    async def show_streaming_defense(self, accused, defense_stream):
        """显示流式被告辩护"""
        import asyncio
        
        # 显示被告名称
        defense_prefix = Text()
        defense_prefix.append(f"🛡️ {accused.name}：", style="bold yellow")
        self.console.print(defense_prefix, end="")
        
        # 流式显示辩护内容
        full_defense = ""
        async for chunk in defense_stream:
            if chunk:
                chunk_text = Text(chunk, style="italic yellow")
                self.console.print(chunk_text, end="")
                full_defense += chunk
                await asyncio.sleep(0.02)
        
        self.console.print()
        self.console.print()
        return full_defense
    
    async def show_streaming_testimony(self, witness, testimony_stream):
        """显示流式证人证词"""
        import asyncio
        
        # 显示证人名称
        testimony_prefix = Text()
        testimony_prefix.append(f"👤 {witness.name}({witness.occupation})：", style="bold green")
        self.console.print(testimony_prefix, end="")
        
        # 流式显示证词内容
        full_testimony = ""
        async for chunk in testimony_stream:
            if chunk:
                chunk_text = Text(chunk, style="italic green")
                self.console.print(chunk_text, end="")
                full_testimony += chunk
                await asyncio.sleep(0.02)
        
        self.console.print()
        self.console.print()
        return full_testimony

    def show_accusation_trial(self, accusation):
        """显示完整的指控审判过程"""
        from models import Accusation
        
        # 显示指控
        self.console.print()
        accusation_text = Text()
        accusation_text.append("⚖️ 正式指控：", style="bold red")
        accusation_text.append(f"指控 {accusation.accused.name} 为凶手", style="red")
        
        accusation_panel = Panel(
            accusation_text,
            title="开庭审理",
            border_style="red",
            padding=(1, 2)
        )
        self.console.print(accusation_panel)
        
        # 显示指控理由
        reasoning_panel = Panel(
            f"🕵️ 侦探的指控理由：\n{accusation.accuser_reasoning}",
            title="指控陈述",
            border_style="blue"
        )
        self.console.print(reasoning_panel)
        input("\n按回车键继续...")
        
        # 显示被指控者的反驳
        defense_panel = Panel(
            f"🛡️ {accusation.accused.name}的反驳：\n{accusation.accused_defense}",
            title="被告辩护",
            border_style="yellow"
        )
        self.console.print(defense_panel)
        input("\n按回车键继续...")
        
        # 显示证人证词
        if accusation.witness_testimonies:
            self.console.print(Panel("👥 证人证词", title="证人作证", border_style="green"))
            
            for witness, testimony in accusation.witness_testimonies:
                witness_panel = Panel(
                    f"👤 {witness.name}({witness.occupation})：\n{testimony}",
                    title=f"{witness.name}的证词",
                    border_style="green"
                )
                self.console.print(witness_panel)
                input("\n按回车键继续...")
        
        # 显示投票环节
        if accusation.votes:
            self.console.print(Panel("🗳️ 陪审团投票", title="投票环节", border_style="purple"))
            
            for voter, vote_result, vote_reason in accusation.votes:
                vote_color = "green" if vote_result == "支持" else "red"
                vote_icon = "✅" if vote_result == "支持" else "❌"
                
                vote_panel = Panel(
                    f"{vote_icon} {voter.name}({voter.occupation})：{vote_result}指控\n理由：{vote_reason}",
                    title=f"{voter.name}的投票",
                    border_style=vote_color
                )
                self.console.print(vote_panel)
                input("\n按回车键继续...")
            
            # 显示投票统计
            vote_summary = accusation.vote_summary
            support_count = vote_summary["support"]
            oppose_count = vote_summary["oppose"]
            total_count = vote_summary["total"]
            
            summary_text = f"""
🗳️ 投票统计：
✅ 支持指控：{support_count}票
❌ 反对指控：{oppose_count}票
📊 总票数：{total_count}票

需要过半数({total_count//2 + 1}票)支持才能定罪
            """
            
            summary_panel = Panel(
                summary_text,
                title="投票结果统计",
                border_style="cyan"
            )
            self.console.print(summary_panel)
            input("\n按回车键继续...")
        
        # 显示最终判决
        if accusation.final_verdict:
            vote_summary = accusation.vote_summary
            vote_info = f"投票结果：{vote_summary['support']}/{vote_summary['total']}票支持"
            self.show_success(accusation.accused, "", vote_info)
        else:
            vote_summary = accusation.vote_summary
            vote_info = f"投票结果：{vote_summary['support']}/{vote_summary['total']}票支持（未过半数）"
            self.show_failure(accusation.accused, "", vote_info)
    
    def confirm_accusation(self, suspect) -> bool:
        """确认是否要指控该嫌疑人"""
        confirm_text = f"""
⚠️  你即将正式指控 {suspect.name} 为凶手！

这将开启正式的审判程序：
1. 你需要陈述指控理由
2. {suspect.name} 将为自己辩护
3. 其他在场人员将作证
4. 所有人员将对指控进行投票
5. 只有过半数支持才能定罪成功

确定要指控 {suspect.name} 吗？
        """
        
        confirm_panel = Panel(
            confirm_text,
            title="⚖️ 确认指控",
            border_style="red"
        )
        
        self.console.print(confirm_panel)
        return Confirm.ask("[bold red]确定要进行正式指控吗？[/bold red]") 